package cn.cxyxj.study.webflux02;

import cn.cxyxj.study.webflux02.account.UserNamePasswordJsonAuthenticationConverter;
import cn.cxyxj.study.webflux02.account.UserServiceImpl;
import cn.cxyxj.study.webflux02.email.EmailReactiveAuthenticationManager;
import cn.cxyxj.study.webflux02.email.EmailAuthenticationWebFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.authentication.UserDetailsRepositoryReactiveAuthenticationManager;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.authentication.AuthenticationWebFilter;

/**
 * @author cxyxj
 */
@Configuration
public class SecurityConfig {

    @Autowired
    private EmailReactiveAuthenticationManager emailReactiveAuthenticationManager;

    @Autowired
    private CustomAuthenticationFailHandler customAuthenticationFailHandler;

    @Autowired
    private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;

    @Autowired
    private CustomAuthenticationEntryPoint customAuthenticationEntryPoint;

    @Autowired
    private CustomAccessDeniedHandler customAccessDeniedHandler;

    //    @Bean
//    SecurityWebFilterChain webFluxSecurityFilterChain(ServerHttpSecurity http) {
//        http.authorizeExchange()
//                .pathMatchers("/hello-dev").hasRole("dev")
//                .pathMatchers("/hello-test").hasRole("test")
//                .anyExchange().authenticated()
//                .and().exceptionHandling().authenticationEntryPoint(customAuthenticationEntryPoint).accessDeniedHandler(customAccessDeniedHandler)
//                .and().cors().disable()
//                .csrf().disable();
//
//        // 自定义邮箱登录
//        EmailAuthenticationWebFilter customEmailAuthenticationWebFilter = new EmailAuthenticationWebFilter(emailReactiveAuthenticationManager);
//        http.addFilterBefore(customEmailAuthenticationWebFilter, SecurityWebFiltersOrder.FORM_LOGIN);
//        customEmailAuthenticationWebFilter.setAuthenticationFailureHandler(customAuthenticationFailHandler);
//        customEmailAuthenticationWebFilter.setAuthenticationSuccessHandler(customAuthenticationSuccessHandler);
//
//        SecurityWebFilterChain build = http.build();
//        return build;
//    }
    @Bean
    SecurityWebFilterChain webFluxSecurityFilterChain(ServerHttpSecurity http) throws Exception {
        http.authorizeExchange()
                .pathMatchers("/hello-dev").hasRole("dev")
                .pathMatchers("/hello-test").hasRole("test")
                .anyExchange().authenticated()
                // 因为我们已经提供了一个 EmailReactiveAuthenticationManager 类，所以需要手动赋值，不然获取到的就是 EmailReactiveAuthenticationManager
                // 具体取值逻辑：ServerHttpSecurityConfiguration.authenticationManager
                .and().formLogin().loginPage("/auth-login").authenticationManager(authenticationManager())
                .authenticationFailureHandler(customAuthenticationFailHandler)
                .authenticationSuccessHandler(customAuthenticationSuccessHandler)
                .and().exceptionHandling().accessDeniedHandler(customAccessDeniedHandler).authenticationEntryPoint(customAuthenticationEntryPoint)
                .and().cors().disable()
                .csrf().disable();

        // 自定义邮箱登录
        EmailAuthenticationWebFilter customEmailAuthenticationWebFilter = new EmailAuthenticationWebFilter(emailReactiveAuthenticationManager);
        http.addFilterBefore(customEmailAuthenticationWebFilter, SecurityWebFiltersOrder.FORM_LOGIN);
        customEmailAuthenticationWebFilter.setAuthenticationFailureHandler(customAuthenticationFailHandler);
        customEmailAuthenticationWebFilter.setAuthenticationSuccessHandler(customAuthenticationSuccessHandler);

        SecurityWebFilterChain build = http.build();
        // 对默认用户名密码登录过滤器 AuthenticationWebFilter 设置 JOSN 格式的转换器
        build.getWebFilters().filter(webFilter -> webFilter instanceof AuthenticationWebFilter)
                .subscribe(webFilter -> {
                    AuthenticationWebFilter filter = (AuthenticationWebFilter) webFilter;
                    filter.setServerAuthenticationConverter(new UserNamePasswordJsonAuthenticationConverter());
                });
        return build;
    }

    /**
     * 设置默认的用户名密码登录相关信息
     */
    @Autowired
    UserServiceImpl userDetailService;

    @Bean
    PasswordEncoder passwordEncoder() {
        return  NoOpPasswordEncoder.getInstance();
    }

    @Bean
    public ReactiveAuthenticationManager authenticationManager() {
        UserDetailsRepositoryReactiveAuthenticationManager authenticationManager = new UserDetailsRepositoryReactiveAuthenticationManager(userDetailService);
        authenticationManager.setPasswordEncoder(passwordEncoder());
        return authenticationManager;
    }

}
